//! Plugin models
//! 
//! This module defines plugin-related data structures for the Extism plugin system.

use crate::models::{Value, ValueMap};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

/// Plugin manifest
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginManifest {
    /// Plugin ID
    pub id: Uuid,
    
    /// Plugin name
    pub name: String,
    
    /// Plugin version
    pub version: String,
    
    /// Plugin description
    pub description: Option<String>,
    
    /// Plugin author
    pub author: Option<String>,
    
    /// Plugin type
    pub plugin_type: PluginType,
    
    /// Plugin entry point
    pub entry_point: String,
    
    /// Plugin configuration schema
    pub config_schema: Option<Value>,
    
    /// Plugin capabilities
    pub capabilities: Vec<String>,
    
    /// Plugin dependencies
    pub dependencies: Vec<String>,
}

/// Plugin information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginInfo {
    /// Plugin manifest
    pub manifest: PluginManifest,
    
    /// Plugin file path
    pub path: String,
    
    /// Plugin status
    pub status: PluginStatus,
    
    /// Plugin configuration
    pub config: ValueMap,
}

/// Plugin types
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum PluginType {
    /// WebAssembly plugin
    Wasm,
    
    /// Python plugin
    Python,
    
    /// JavaScript plugin
    JavaScript,
    
    /// Go plugin
    Go,
    
    /// Rust plugin
    Rust,
    
    /// Custom plugin type
    Custom(String),
}

/// Plugin status
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PluginStatus {
    /// Plugin is loaded and ready
    Loaded,
    
    /// Plugin is loading
    Loading,
    
    /// Plugin failed to load
    Failed(String),
    
    /// Plugin is unloaded
    Unloaded,
}

impl PluginManifest {
    /// Create a new plugin manifest
    pub fn new(name: String, version: String, plugin_type: PluginType) -> Self {
        Self {
            id: Uuid::new_v4(),
            name,
            version,
            description: None,
            author: None,
            plugin_type,
            entry_point: "main".to_string(),
            config_schema: None,
            capabilities: Vec::new(),
            dependencies: Vec::new(),
        }
    }
}

impl PluginInfo {
    /// Create new plugin info
    pub fn new(manifest: PluginManifest, path: String) -> Self {
        Self {
            manifest,
            path,
            status: PluginStatus::Unloaded,
            config: ValueMap::new(),
        }
    }
    
    /// Check if plugin is loaded
    pub fn is_loaded(&self) -> bool {
        matches!(self.status, PluginStatus::Loaded)
    }
    
    /// Check if plugin has capability
    pub fn has_capability(&self, capability: &str) -> bool {
        self.manifest.capabilities.contains(&capability.to_string())
    }
}
